package com.eascs.workflow.email.service.impl;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.eascs.app.log.Logger;
import com.eascs.app.log.LoggerFactory;
import com.eascs.app.runtime.RuntimeSetting;
import com.eascs.common.util.UuidUtil;
import com.eascs.web.sso.User;
import com.eascs.workflow.common.entity.sys.SysEmail;
import com.eascs.workflow.common.entity.wf.ProcessTaskMain;
import com.eascs.workflow.common.entity.wf.ProcessTaskNode;
import com.eascs.workflow.common.entity.wf.ProcessTemplate;
import com.eascs.workflow.common.entity.wf.TaskNodeAuditor;
import com.eascs.workflow.email.dao.SysSendEmailOrMessageDao;
import com.eascs.workflow.email.service.WFEmailService;
import com.eascs.workflow.email.vo.TimeEffectiveEmailVO;
import com.eascs.workflow.email.vo.WFEmailContentVO;
import com.eascs.workflow.sys.dao.SysUserDao;
import com.eascs.workflow.wf.dao.ProcessTaskMainDao;
import com.eascs.workflow.wf.dao.TaskNodeAuditorDao;
import com.eascs.workflow.wf.entity.WorkWarnEntity;
import com.eascs.notify.mail.MailNotifier;
import com.eascs.notify.mail.MailNotifyRequest;
import com.eascs.notify.mail.MailSendType;

import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;

@Service
public class WFEmailServiceImpl implements WFEmailService {
	private static Logger log = LoggerFactory.getLogger(WFEmailServiceImpl.class);
	/** 邮件待办人 */
	private static final String MAIL_TO_UNDOER = "undoer";
	/** 邮件经办人 */
	private static final String MAIL_TO_OPERATOR = "operator";
	/** 回复主加签人 */
	private static final String MAIL_TO_BACK_SIGN = "backToSign";
	/** 待办URL */
	// private String undoUrl =
	// "%s/wf/approval?loanapplyNo=%s&nodeAuditorId=%s";
	private String undoUrl = "%s/wf/queryTask?approvalStatus=UNDO";
	/** 贷款详情URL */
	private String loanDetailUrl = "%s/detail?loanapplyNo=%s";
	@Autowired
	private SysUserDao sysUserDao;
	@Autowired
	private SysSendEmailOrMessageDao dao;
	@Autowired
	private ProcessTaskMainDao processTaskMainDao;
	@Autowired
	private TaskNodeAuditorDao taskNodeAuditorDao;
	@Value("${web.homeUrl}")
	private String serviceUrl;
	@Value("${o2o.workflow.env}")
	private String env;
	@Reference
	private MailNotifier mailNotifier;

	private String convertEmailContent(WFEmailContentVO vo) {
		// 通过指定模板名获取FreeMarker模板实例
		try {
			Configuration configuration = new Configuration(Configuration.VERSION_2_3_24);
			configuration.setTemplateLoader(new ClassTemplateLoader(this.getClass(), "/email/"));
			Template template = configuration.getTemplate("wfEmailTemplate.ftl");
			StringWriter stringWriter = new StringWriter();
			// FreeMarker通过Map传递动态数据
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("email", vo);
			template.process(map, stringWriter);
			String htmlText = stringWriter.toString();
			return htmlText;
		} catch (Exception e) {
			log.error("生成邮件模板失败", e);
		}
		return null;
	}
	
	private String convertTimeEffectiveEmailContent(TimeEffectiveEmailVO vo) {
		// 通过指定模板名获取FreeMarker模板实例
		try {
			Configuration configuration = new Configuration(Configuration.VERSION_2_3_24);
			configuration.setTemplateLoader(new ClassTemplateLoader(this.getClass(), "/email/"));
			Template template = configuration.getTemplate("timeEffectiveEmailTemplate.ftl");
			StringWriter stringWriter = new StringWriter();
			// FreeMarker通过Map传递动态数据
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("email", vo);
			template.process(map, stringWriter);
			String htmlText = stringWriter.toString();
			return htmlText;
		} catch (Exception e) {
			log.error("生成邮件模板失败", e);
		}
		return null;
	}

	private String convertWarnEmailContent(List<WorkWarnEntity> vo) {
		// 通过指定模板名获取FreeMarker模板实例
		try {
			Configuration configuration = new Configuration(Configuration.VERSION_2_3_24);
			configuration.setTemplateLoader(new ClassTemplateLoader(this.getClass(), "/email/"));
			Template template = configuration.getTemplate("workWarnEmailTemplate.ftl");
			StringWriter stringWriter = new StringWriter();
			// FreeMarker通过Map传递动态数据
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("workWarn", vo);
			template.process(map, stringWriter);
			String htmlText = stringWriter.toString();
			return htmlText;
		} catch (Exception e) {
			log.error("生成邮件模板失败", e);
		}
		return null;
	}

	private void notifyEmail(ProcessTaskMain taskMain, List<TaskNodeAuditor> unDoList, List<String> toOperatorList, String mailToType) {
		try {
			log.info("referCode:[{}],taskCode:[{}],开始发送邮件入库", taskMain.getReferCode(), taskMain.getTaskCode());
			// 查找发送人的信息
			List<MailEntry> mailEntryList = getToMailList(unDoList, toOperatorList, mailToType);
			if (mailEntryList != null && !mailEntryList.isEmpty()) {
				for (MailEntry entry : mailEntryList) {
					//SysEmail sysEmail = new SysEmail();
					MailNotifyRequest mailNotifyRequest=new MailNotifyRequest();
					mailNotifyRequest.setSystemCode("工作流系统");
					mailNotifyRequest.setMailSendType(MailSendType.INSTANT);
					mailNotifyRequest.setBizCode(taskMain.getTaskCode());
					mailNotifyRequest.setRequestId(UuidUtil.generateShortUuid());
					
					String title = null;
					String processStatus = "审核中";
					if (StringUtils.equals(mailToType, MAIL_TO_BACK_SIGN)) {
						title = "您加签的【" + taskMain.getProcessName() + "】审批已审批完成";
					} else {
						// 审核中
						if (taskMain.getProcessStatus() == ProcessTaskMain.PROECESS_STATUS_HANDING) {
							title = "有新提交的【" + taskMain.getProcessName() + "】需要您审批，单号【" + taskMain.getTaskCode() + "】，申请人【" + taskMain.getAppliedbyName() + "】，申请时间【"
									+ DateFormatUtils.format(taskMain.getAppliedDate(), "yyyy-MM-dd HH:mm:ss") + "】";
						} else if (taskMain.getProcessStatus() == ProcessTaskMain.PROECESS_STATUS_PASS) {
							title = "您于【" + DateFormatUtils.format(taskMain.getAppliedDate(), "yyyy-MM-dd HH:mm:ss") + "】提交的【" + taskMain.getProcessName() + "】已【审核通过】";
							processStatus = "审核通过";
						} else if (taskMain.getProcessStatus() == ProcessTaskMain.PROECESS_STATUS_TURNED_DOWN) {
							title = "您于【" + DateFormatUtils.format(taskMain.getAppliedDate(), "yyyy-MM-dd HH:mm:ss") + "】提交的【" + taskMain.getProcessName() + "】已【驳回】";
							processStatus = "已驳回";
						} else if (taskMain.getProcessStatus() == ProcessTaskMain.PROECESS_STATUS_CLOSE) {
							title = "您于【" + DateFormatUtils.format(taskMain.getAppliedDate(), "yyyy-MM-dd HH:mm:ss") + "】提交的【" + taskMain.getProcessName() + "】已【关闭】";
							processStatus = "已关闭";
						}
					}
					
					mailNotifyRequest.setTitle(title);
					mailNotifyRequest.setRecipientTo(entry.getMail());
					mailNotifyRequest.setRequestDateTime(new Date());
//					sysEmail.setTitle(title);
//					sysEmail.setRecipients(entry.getMail());
//					sysEmail.setStatus(0);
//					sysEmail.setCreateTime(new Date());

					// 生成邮件内容
					WFEmailContentVO contentVo = new WFEmailContentVO();
					contentVo.setTitle("O2O金融【" + taskMain.getProcessName() + "】");
					contentVo.setLoanNo(taskMain.getReferCode());
					contentVo.setWfNo(taskMain.getTaskCode());
					contentVo.setProposer(taskMain.getAppliedbyName());
					contentVo.setProposTime(DateFormatUtils.format(taskMain.getAppliedDate(), "yyyy-MM-dd HH:mm:ss"));
					contentVo.setStatus(processStatus);
					contentVo.setCreateTime(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
					contentVo.setMialType(mailToType);
					contentVo.setLoanDes(taskMain.getAppliedDes());
					// 生成单号链接
					if (StringUtils.equals(mailToType, MAIL_TO_UNDOER) || StringUtils.equals(mailToType, MAIL_TO_BACK_SIGN)) {
						String url = String.format(undoUrl, serviceUrl);
						contentVo.setToDoUrl(url);
					} else {
						String url = String.format(loanDetailUrl, serviceUrl, taskMain.getReferId());
						contentVo.setLoanDetailUrl(url);
					}
					String content = convertEmailContent(contentVo);
					if (StringUtils.isNotBlank(content)) {
//						sysEmail.setContent(content);
//						dao.insertEmail(sysEmail);
						mailNotifyRequest.setContent(content);
						mailNotifier.notify(mailNotifyRequest);
						log.info("referCode:[{}],taskCode:[{}],toList:[{}],开始发送邮件入库成功", taskMain.getReferCode(), taskMain.getTaskCode(), entry.getMail());
					} else {
						log.info("referCode:[{}],taskCode:[{}],toList:[{}],生成邮件内容为空", taskMain.getReferCode(), taskMain.getTaskCode(), entry.getMail());
					}
				}
			}
		} catch (Exception e) {
			log.error("referCode:[" + taskMain.getReferCode() + "],邮件发送入库失败,errorMsg:[{}]", e.getMessage());
		}
	}

	@Override
	public void notifyEmailToDo(ProcessTaskMain taskMain, List<TaskNodeAuditor> toDoList,ProcessTaskNode taskNode) {
		if(taskNode.getIsSendEmail() != null && taskNode.getIsSendEmail() == 0){
			log.info("节点配置不发送邮件");
			return;
		}
		notifyEmail(taskMain, toDoList, null, MAIL_TO_UNDOER);
	}

	/**
	 * 获取邮件列表
	 * 
	 * @param unDoList
	 * @param toOperatorList
	 * @param mailToType
	 * @return
	 */
	private List<MailEntry> getToMailList(List<TaskNodeAuditor> unDoList, List<String> toOperatorList, String mailToType) {
		RuntimeSetting runtimeSetting = RuntimeSetting.get();
		List<MailEntry> entryList = new ArrayList<MailEntry>();

		if (runtimeSetting.getEnv().equals("prod")) { // 生产环境
			if (StringUtils.equals(mailToType, MAIL_TO_UNDOER) || StringUtils.equals(mailToType, MAIL_TO_BACK_SIGN)) {
				for (TaskNodeAuditor auditor : unDoList) {
					MailEntry entry = new MailEntry();
					User user = sysUserDao.getSysUserById(auditor.getAuditorNo());
					entry.setTaskAuditorId(auditor.getNodeAuditorId());
					entry.setMail(user.getEmail());
					entry.setAuditorName(auditor.getAuditorName());
					entryList.add(entry);
				}
			} else {
				for (String userNo : toOperatorList) {
					MailEntry entry = new MailEntry();
					User user = sysUserDao.getSysUserById(userNo);
					entry.setMail(user.getEmail());
					entryList.add(entry);
				}
			}
			return entryList;
		} else {
			if (StringUtils.equals(mailToType, MAIL_TO_UNDOER) || StringUtils.equals(mailToType, MAIL_TO_BACK_SIGN)) {
				for (TaskNodeAuditor auditor : unDoList) {
					MailEntry entry = new MailEntry();
					entry.setTaskAuditorId(auditor.getNodeAuditorId());
					entry.setMail("jun.lu@eascs.com");
					entry.setAuditorName("jun.lu");
					entryList.add(entry);
				}
			} else {
				for (int i = 0; i < toOperatorList.size(); i++) {
					MailEntry entry = new MailEntry();
					entry.setMail("jun.lu@eascs.com");
					entryList.add(entry);
				}
			}
			return entryList;
		}
	}

	class MailEntry {
		private String mail;
		private String taskAuditorId;
		
		/** 审核人姓名 */
		private String auditorName;

		public String getMail() {
			return mail;
		}

		public void setMail(String mail) {
			this.mail = mail;
		}

		public String getTaskAuditorId() {
			return taskAuditorId;
		}

		public void setTaskAuditorId(String taskAuditorId) {
			this.taskAuditorId = taskAuditorId;
		}

		public String getAuditorName() {
			return auditorName;
		}

		public void setAuditorName(String auditorName) {
			this.auditorName = auditorName;
		}
		
		
	}

	@Override
	public void notifyEmailToOperator(ProcessTaskMain taskMain, List<String> toOperatorList) {
		notifyEmail(taskMain, null, toOperatorList, MAIL_TO_OPERATOR);
	}

	@Override
	public void WorkWarnEmail(List<WorkWarnEntity> toList) {
		WorkWarnEntity ww = toList.get(0);
		try {
			String title="待办单据日报";
			MailNotifyRequest mailNotifyRequest=new MailNotifyRequest();
			mailNotifyRequest.setSystemCode("工作流系统");
			mailNotifyRequest.setMailSendType(MailSendType.INSTANT);
			mailNotifyRequest.setTitle(title);
			mailNotifyRequest.setBizCode(ww.getTaskCode());
			mailNotifyRequest.setRequestId(UuidUtil.generateShortUuid());
			
			//SysEmail sysEmail = new SysEmail();
			//sysEmail.setTitle(title);
			if (env.equals("prod")) {
				//sysEmail.setRecipients(ww.getEmail());
				mailNotifyRequest.setRecipientTo(ww.getEmail());
			}else{
				// 测试
				//sysEmail.setRecipients("jun.lu@eascs.com");
				mailNotifyRequest.setRecipientTo("jun.lu@eascs.com");
			}
			log.info("wfWorkWarn.save.email env:[{}]",env);
//			sysEmail.setStatus(0);
//			sysEmail.setCreateTime(new Date());
			mailNotifyRequest.setRequestDateTime(new Date());
			String content = convertWarnEmailContent(toList);
			if (StringUtils.isNotBlank(content)) {
//				sysEmail.setContent(content);
				//dao.insertEmail(sysEmail);
				mailNotifyRequest.setContent(content);
				mailNotifier.notify(mailNotifyRequest);
				log.info("wfWorkWarn.save.email.success!! email:[{}],待办24小时提醒邮件入库成功", ww.getEmail());
			} else {
				log.info("wfWorkWarn.save.email.fail!! email:[{}],生成邮件内容为空 ,content:[{}]", ww.getEmail(), content);
			}
		} catch (Exception e) {
			log.info("wfWorkWarn.save.email.fail!! email:[{}],待办24小时提醒邮件入库失败,error:[{}]", ww.getEmail(),e.getMessage());
		}
	}

	@Override
	public void notifyEmailToMainSign(ProcessTaskMain taskMain, List<TaskNodeAuditor> toList,ProcessTaskNode taskNode) {
		if(taskNode.getIsSendEmail() != null && taskNode.getIsSendEmail() == 0){
			log.info("节点配置不发送邮件");
			return;
		}
		notifyEmail(taskMain, toList, null, MAIL_TO_BACK_SIGN);
	}

	@Override
	public void notifyEmailTimeEffective(ProcessTaskNode taskNode) {
		MailNotifyRequest mailNotifyRequest=null;
		RuntimeSetting runtimeSetting = RuntimeSetting.get();
		try {
			log.info("taskId:[{}],TaskNodeId:[{}],开始发送邮件入库", taskNode.getTaskId(), taskNode.getTaskNodeId());
			
			ProcessTaskMain taskMain=processTaskMainDao.getTaskMainListByTaskId(taskNode.getTaskId());
			List<TaskNodeAuditor> unDoList=taskNodeAuditorDao.getNodeAuditors(taskNode.getTaskNodeId());
			// 查找发送人的信息
			List<MailEntry> mailEntryList = getToMailList(unDoList,null, MAIL_TO_BACK_SIGN);
			if (mailEntryList != null && !mailEntryList.isEmpty()) {
				for (MailEntry entry : mailEntryList) {
					mailNotifyRequest=new MailNotifyRequest();
					mailNotifyRequest.setSystemCode("工作流系统");
					mailNotifyRequest.setMailSendType(MailSendType.INSTANT);
					mailNotifyRequest.setBizCode(taskMain.getTaskCode());
					mailNotifyRequest.setRequestId(UuidUtil.generateShortUuid());
					
					String title = "超时待办提醒["+taskMain.getTaskCode()+"] ： 您有一个待办流程超时需要处理";
					String processStatus = "审核中";
					
					mailNotifyRequest.setTitle(title);
					mailNotifyRequest.setRecipientTo(entry.getMail());
					mailNotifyRequest.setRequestDateTime(new Date());

					// 生成邮件内容
					TimeEffectiveEmailVO contentVo = new TimeEffectiveEmailVO();
					contentVo.setTitle(title);
					contentVo.setLoanNo(taskMain.getReferCode());
					contentVo.setWfNo(taskMain.getTaskCode());
					contentVo.setProposer(taskMain.getAppliedbyName());
					contentVo.setProposTime(DateFormatUtils.format(taskMain.getAppliedDate(), "yyyy-MM-dd HH:mm:ss"));
					contentVo.setStatus(processStatus);
					contentVo.setCreateTime(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
					contentVo.setMialType(MAIL_TO_UNDOER);
					contentVo.setLoanDes(taskMain.getAppliedDes());
					contentVo.setNodeProposer(entry.getAuditorName());
					contentVo.setProcessTaskNodeName(taskNode.getNodeName());
					contentVo.setOrgName(taskMain.getOrgName());
					// 生成单号链接
					String url = String.format(undoUrl, serviceUrl);
					contentVo.setToDoUrl(url);
					String content = convertTimeEffectiveEmailContent(contentVo);
					if (StringUtils.isNotBlank(content)) {
						mailNotifyRequest.setContent(content);
						mailNotifier.notify(mailNotifyRequest);
						log.info("referCode:[{}],taskCode:[{}],toList:[{}],【节点处理人】开始发送邮件入库成功", taskMain.getReferCode(), taskMain.getTaskCode(), entry.getMail());
					} else {
						log.info("referCode:[{}],taskCode:[{}],toList:[{}],生成邮件内容为空", taskMain.getReferCode(), taskMain.getTaskCode(), entry.getMail());
					}
				}
				if(mailNotifyRequest != null && StringUtils.equals(taskMain.getProcessType(), ProcessTemplate.PROECESS_TYPE_ARCHIVE)){
					User user = sysUserDao.getSysUserById(taskMain.getAppliedby());
					if (runtimeSetting.getEnv().equals("prod")) { // 生产环境
						mailNotifyRequest.setRecipientTo(user.getEmail());
					}
					else{
						mailNotifyRequest.setRecipientTo("jun.lu@eascs.com");	
					}
					mailNotifier.notify(mailNotifyRequest);
					log.info("referCode:[{}],taskCode:[{}],toList:[{}],【流程发起人】开始发送邮件入库成功", taskMain.getReferCode(), taskMain.getTaskCode(), user.getEmail());
				}
			}
		} catch (Exception e) {
			log.error("TaskId:[{}],TaskNodeId:[{}],邮件发送入库失败,errorMsg:[{}]",taskNode.getTaskId(),taskNode.getTaskNodeId(), e.getMessage());
		}
	
	}
}